Тут будет «сборник рецептов», представляющих собой функции, сохраненные в переменные мейкера. Часть из них можно использовать сами по себе, часть требует наличия других связанных функций. Повторюсь, при желании, все из этого можно вынести в отдельный плагин…по сути, это самый оптимальный вариант работы.
Большая часть кода практически использовалась в игре “ALWBAW”, ее же можно рассматривать как демо-версию – игра не зашифрована, ее можно открыть редактором (подбросив файл проекта MZ); если будете открывать – особый интерес представляют первые три «технические» карты и Общие события. Игру можно найти на данном форуме, на Светлой полосе, на Юнионе.
Если «рецепт» в реальной игре не тестировался – это будет указано отдельно.
Демо-игра также использует логику «сопартиец-как-патрон», что в рамках данного туториала рассматриваться не будет.
В существенной части рецептов используется применение скрипта в Маршруте эвента и тот факт, что на скорость исполнения маршрута влияет частота эвента. Также используется возможность хранения и записи текста в Примечании эвента. Кроме того, для ряда рецептов (прыжок, платформы) используется задание регионов на карте – во всех примерах корректным является регион с номером «1» (это тоже можно менять).
У каждого эвента-врага специальным образом заполнено Примечание и две страницы – первая, активируемая лок. переключателем «A» активная и вторая, активируемая лок. переключателем «B» не активная (враг уничтожен).
У эвентов-"пулек" и эвентов-"бомб" - три страницы, первая пустая не активная (но уже с нужной графикой!), вторая и третья как у эвентов-врагов
Номера функций в примерах кода взяты из игры, вы можете ставить любые. Код приводится в «сжатом» варианте – гарантированно влезает в команду «Скрипт» на MZ. Скриншотов не будет.
Код, как и логику что он реализует, может быть не оптимальна.
СпойлерРецепт №1. «Прыжок с проверкой допустимости конечной точки»:
Цель:
Игрок прыгает на N-клеток вперед в сторону, которую повернут лицом (это называется «направление» в контексте мейкера) и только в том случае, если конечная точка допустима для приземления (чтоб не оказаться в стене, яме, итд). Направление передается из вызывающего кода.
Логика:
Согласно направлению и дальности прыжка, нужно узнать является ли конечная точка допустимым местом приземления. Для этого, исходя из направления, рассчитываются координаты корректной точки и проверяется ее номер ее региона.
В случае, если конечная точка нам подходит, то так как прыжок работает по разнице координат, мы получаем текущие координаты игрока, вычисляем разницу с конечными координатами и вызываем для игрока встроенную функцию прыжка по вычисленным значениям. В коде также вызывается дрожь экрана и SE-звук, причем отдельный звук в случаях прыжка и отказа.
Что можно улучшить:
Можно задать динамическую дальность прыжка, храня «радиус» в отдельной переменной. Можно сделать так, что в случае некоррктности конечной клетки, проверяется корректность предыдущий…и игрок прыгает хоть как-то. Можно хранить стартовые (до-прыжковые) координаты игрока в отдельной переменной.
СпойлерРецепт №2. «Клонирование эвента с его последующей активацией»:
Цель:
Создать новый эвент программно, по образцу уже существующего. При этом существующий эвент «не активен», т.е. первая страница пуста, а для работы он требует включеный локальный переключатель «A». При этом новый эвент создается по конкретным координатам с конкретным направлением. Id эвента для копирования, необходимые координаты и направление передаются из вызывающего кода.
Логика:
Копируем эвент, задаем ему новый случайный Id (цифры 1000 и 500 произвольны и исходят из кол-во ОБЫЧНЫХ, не клонированных, эвентов на карте), вставляем его в массивы эвентов игровые объектов $dataMap и $gameMap (для второго предварительно нужно создать новый «игровой» эвент), задаем новому эвенту направление, перемещаем в координаты, включаем у него «активный» локальный переключатель и обновляем графику всех эвентов на карте (сцене), тем самым делая клонированный эвент видимым.
Что можно улучшить:
Вероятно, можно улучшить генерацию случайного Id для нового эвента, введя доп. проверки на наличие таких Id.
СпойлерРецепт №3. «Понижение ХП игрока, урон по игроку»:
Цель:
Программного снижать ХП игрока (точнее, первого персонажа-лидера, в партии).
Логика:
Получаем объект игрока (лидера партии), меняем ХП с разрешением смерти.
Код функции Снижения ХП:
Код:
$gameVariables.setValue(9, () => {
let player = $gameParty.leader();
let decrValue = -1;
let canKO = true;
this.changeHp(player, decrValue, canKO);
});
Что можно улучшить:
Можно сделать, что бы величина уменьшения ХП передавалась в функцию снаружи и не была константой.
СпойлерРецепт №4. «Шипы»:
Цель:
Получить эвент, циклически меняющий свое состояние (фазы) и графику, при некоторых состояниях себя наносящий урон игроку, что находится на эвенте или проходит через него…т.е. наши любимые шипы. Желательно – без параллельных событий и «мучений» с графикой и маршрутом эвента.
Логика:
Эвент под персонажем, фиксированный.
У эвента четыре страницы (они же стостояния-фазы), первая не требует локальные переключатели, следующие требуют включения «A», «B», «C».
У эвента нормальная скорость и максимальная частота, у каждой страницы своя графика шипов.
У каждой страницы задан маршрут, а именно:
1) Первая страница – ждать 30 секунд и выполнить скрипт для включения лок. Переключателя «A».
2) Вторая страница – ждать 30 секунд и выполнить скрипт для включения лок. Переключателя «B» с выключением лок. переключателя «A».
3) Третья страница – выполнить код урона шипов для маршрута, ждать 30 секунд и выполнить скрипт для включения лок. переключателя «C» с выключением лок. переключателей «A» и «B».
4) Четвертая страница – выполнить код урона шипов для маршрута, ждать 30 секунд и выполнить скрипт для выключения лок. переключателей «A», «B» и «C».
Третья и четвертые страницы, кроме маршрута, активируются от касания игрока и выполняют специальный скрипт (урон игроку и показ анимации).
Логика скрипта в маршруте – проверка координат игрока и если совпадают с координатами эвента, то урон игроку и анимация.
Код в маршрурте, для переключения страницы-состояния (маршрут Повторяется, код должен быть одной строкой - но форум "поломал"):
Цель:
Движущаяся эвент-платформа, на которую игрок может стать, и которая «красиво» транспортирует игрока в заданную точку.
Логика:
Эвент под персонажем.
У эвента две страницы, в маршруте одной задается движение в нужную сторону, в маршруте другой – возврат к исходной точке; вторая страница включается лок. переключателем «A».
Скорость нормальная, частота максимальная, графика на страницах может быть одинаковая / разная.
Маршрут (маршрут Повторяется):
1) Выключается проходимость.
2) Ожидание 120 фреймов.
3) Включается проходимость.
4) …ставится нужное кол-во шагов, для достижения конечной точки…
5) Выполняется скрипт для включения / выключения лок. переключателя «A» (в зависимости от страницы).
Также каждая страница, кроме маршрута, активируется от касания игрока и выполняет скрипт.
Логика скрипта на странице эвента – получаем объект эвента текущей платформы, задаем его координаты, задаем Схему движения, вызываем Функцию платформы и передаем ей это как аргументы.
Логика функции Платформы – запрет прыжка, определение маршрута движения исходя из Схемы движения, движение пока не платформа не коснется корректного региона (под номером «1»), прыжок игрока на клетку в которую уперлась платформа, включение прыжка.
Что можно улучшить:
В принципе, хотелось бы отвязаться от ручного задания координат в скрипте эвента – но способа я не нашел.
СпойлерРецепт №6. «Жив ли враг»:
Цель:
Узнать, является ли целевой эвент врагом и если да – есть у него еще ХП. Id врага-эвента задается извне.
Логика:
В каждом эвенте, который мы хотим использовать в качестве «врага» в своей АБС, в примечании пишем текст: {"type": "ENEMY", "hp": 3, "countVarId": 26}
То есть, задаем объект с характеристиками:
type – тип;
hp – хп;
countVarId – номер пеменной, в которую плюсуется +1 при уничтожении врага.
Логика кода проверки – получаем Примечание нужного эвента (по его Id), парсим и читаем Примечание, находим и сравниваем ХП. Если ХП ноль и менее, или тип врага не тот, возвращаем false; иначе – true.
Что можно улучшить:
Если типов врагов много, можно сделать доп. проверки.
СпойлерРецепт №7. «Уменьшение ХП врага»:
Цель:
Уменьшение характ-ки ХП эвента-врага. Id врага-эвента задается извне, как и урон.
Логика:
Получаем Примечание нужного эвента (по его Id), парсим и читаем Примечание, уменьшаем ХП, записываем обратно в Примечание эвента.
Если ХП в результате меньше 0, то показываем на врага анимацию, включаем его «побежденный» переключатель «B», делая его тем самым неактивным, и приплюсовываем к переменной для кол-ва уничтоженных врагов единицу (если номер переменной равен 0, он игнорируется мейкером).
ХП возвращается из ф-ии, т.к. это нужно для "бомбы".
Что можно улучшить:
Проверку по ХП. Возможно, добавить в «объект врага» кроме переменной – включение какого-то переключателя, это может быть полезно для Боссов.
СпойлерРецепт №8. «Удар игроком врага в ближнем бою»:
Цель:
Возможность для игрока атаковать эвент, находящийся в небольшой радиусе с ним, уменьшая его ХП.
Логика:
Логика делится на две части:
1) Получения массива координат, в которых будет проходить поиска врагов; это и есть дальность и «радиус» удара; тут он не только перед игроком, но еще и по диагонали влево и вправо – для удобства. Массивы высчитывается исходя их координат игрока и его направления.
2) По найденному массиву координат проходимся циклом, записываем его в массив найденных врагов. После чего проходимся уже по нему и для каждого найденного врага, проверяем жив ли он, и если да – наносим урон по эвенту-врагу и проигрываем анимацию.
Перед вызовом скрипта с кодом атаки в ближнем бою, опционально, можно проиграть анимацию средствами команд мейкера.
Код атаки врага в ближнем бою:
Код:
let getCoordsList = $gameVariables.value(1); let isEnemyyAlive = $gameVariables.value(2)
let changeEnemyHP = $gameVariables.value(3);
let coordsList = getCoordsList($gamePlayer);
let enemiesList = [];
for(let n = 0; n < coordsList.length; n++){
let currentEnemy = $gameMap.eventsXy(coordsList[n][0], coordsList[n][1]);
if(currentEnemy.length > 0){
enemiesList.push(currentEnemy[0]);
}
}
enemiesList.forEach(enemy => {
if(true === isEnemyyAlive(enemy)){
$gameTemp.requestAnimation([enemy], 1);
changeEnemyHP(enemy);
}
});
Код функции Получения массива координат перед игроком:
Что можно улучшить:
Можно сделать несколько видов оружия ближнего боя и, в зависимости от выбранного оружия, менять массив координат для урона (оружие бьет вокруг, бьет с дальностью 2 клетки, бьет букой «Г», итд).
СпойлерРецепт №9. «Удар врагом игрока в ближнем бою»:
Цель:
Эвент-враг атакует игрока, находящегося рядом, понижая его ХП.
Логика:
Логика схожа с логикой удара игроком эвента.
Сначала, исходя из координат атакующего эвента, получаем массив возможных координат атаки (функция в Рецепте №9).
После чего для каждого варианта координат сверяем, совпадают ли они с координатами игрока и если да, то проигрываем на игрока анимации и снижаем его ХП. Опционально, в зависимости от направления эвента, проигрывается анимация «взмаха» оружием.
Все это делает эвент-враг функцией, которую вызываем в маршруте (например: повторяющиеся шаг к игроку и вызов функции).
Мне показалось, что оптимальная частота здесь не максимальная, а высокая.
Код для маршрута:
Код:
let meleeEnemyAttack = $gameVariables.value(11); meleeEnemyAttack(this);
Код функции Атаки врагом игрока в ближнем бою:
Код:
$gameVariables.setValue(11, (enemyEvent) => {
let getCoordsList = $gameVariables.value(1);
let damagePlayer = $gameVariables.value(9);
let coordsList = getCoordsList(enemyEvent);
let direction = enemyEvent._direction;
for(let n = 0; n < coordsList.length; n++){
if(coordsList[n][0] === $gamePlayer._x && coordsList[n][1] === $gamePlayer._y){
if(8 === direction){ $gameTemp.requestAnimation([enemyEvent], 122);
}else if(6 === direction){ $gameTemp.requestAnimation([enemyEvent], 125);
}else if(4 === direction){ $gameTemp.requestAnimation([enemyEvent], 124);
}else if(2 === direction){ $gameTemp.requestAnimation([enemyEvent], 123);
}
$gameTemp.requestAnimation([$gamePlayer], 1);
damagePlayer();
}
}
});
Что можно улучшить:
Если будет несколько типов врагов ближнего боя, для них можно сделать разные массивы координат (разные дальность и радиус удара).
СпойлерРецепт №10. «Выстрел игрока и/или врага»:
Цель:
При активации скрипта, перед игроком / врагом появляется эвент-«пулька» и движется N-ое количество шагов по направлению игрока и / или врага.
Логика:
Логика делится на логику «выстрела» и логику «пульки»
Логика выстрела - получаем координаты клетки перед игроком / врагом, исходя из его направления, в которые будет перемещено клонируемый эвент-«пулька» и клонируем эвент-«пульку».
Логика «пульки» - проходимый фиксированный эвент, с Примечанием {"type": "BULLET", "hp": 7, "countVarId": 0} , в котором ХП обозначает дальность движения. Страница «A» активна, на ней задан маршрут с высокой скоростью и максимальной частотой. В маршруте только выполняется скрипт. Логика функции вызываемого скрипта – каждый шаг «пульки» проверяется, есть ли на ее текущих координатах эвенты и игрок, если есть – анимация на них и им урон, и в любом случае – урон самой «пульке»!
Код функции Клонирования эвента-«пульки»:
Код:
const EVENT_TO_SPAWN_ID = $gameVariables.value(27);
let getFaceSideCoords = $gameVariables.value(4);
let spawnEvent = $gameVariables.value(5);
let direction = $gamePlayer._direction; // для стреляющего врага тут указывается его направление!
let coordsForSpawn = getFaceSideCoords($gamePlayer); //для стреляющего врага тут указывается его эвент!!
spawnEvent(EVENT_TO_SPAWN_ID, coordsForSpawn[0], coordsForSpawn[1], direction);
Код функции Получения координат перед игроком / врагом:
Что можно улучшить:
Если будет несколько видом дальнобойного оружия, можно изменить проходимость (в данном коде «пулька» самоуничтожается после дамага по игроку / врагу), можно сделать несколько эвентов-«пулек» с разной дальностью (ХП) и скоростью. Возможно, копировать «пульку» не перед лицом стреляющего, а в других координатах (над, под, 2-3 пульки).
СпойлерРецепт №11. «Тикающая бомба»:
Цель:
При активации скрипта, на месте игрока / врага создается эвент-бомба, «взрывающийся» через некоторое количество времени.
Логика:
Логика схожа с логикой выстрела, т.к. для клонирования используется специальный объект-«часовая бомба», у которой тоже маршрут со скриптом, и которая тоже наносит себе же урон. При достижении 1 ХП и происходит «взрыв», нанося урон всем (и игроку, и эвентам-врагам) в заданном радиусе.
А еще бобма прыгает в процессе "тикания".
Код для «призыва бомбы»:
Код:
$gameVariables.setValue(15, (enemyEvent) => {
const EVENT_TO_SPAWN_ID = $gameVariables.value(28);
let getFaceSideCoords = $gameVariables.value(4);
let spawnEvent = $gameVariables.value(5);
let direction = enemyEvent._direction;
let coordsForSpawn = getFaceSideCoords(enemyEvent);
spawnEvent(EVENT_TO_SPAWN_ID, coordsForSpawn[0], coordsForSpawn[1], direction);
AudioManager.playSe( { name: 'Bite', volume: 90, pitch: 100, pan: 0 } );
});
Код для маршрута «бомбы»:
Код:
let tickBombEvent = $gameVariables.value(7); tickBombEvent(this);
Что можно улучшить:
Не знаю, мне просто нравится как это работает.
СпойлерРецепт №12. «Вывод информации»:
А тут не будет рецепта, т.к. с графической частью я так и не разобрался.
Для этого лучше использовать плагин: dirge, Galv, Orange…
Я же в демо-игре просто в переменные записывал ХП, патроны и выбранное оружие и показывал в сообщении (ну и цветом экрана + графикой сопартийцев).
Как справедливо заметил Петр, ставить параллельное событие с изменением цвета экрана – не очень мудро…но я так и делал. =)
Чтоб рецепт не был пустым, вот то единственное что я смог найти и сделать для отрисовки окон изнутри мукера:
Код:
var rect = new Rectangle(25, 25, 400, 400);
var win = new Window_Base(rect);
SceneManager._scene.addChild(win);
win.drawTextEx('\\C[18]HP\\V[24]', 125, 150, 350, 'center');
Может быть, вы это сможете довести до вменяемого вида и как-то использовать. В реальной игре это не тестировалось.
где graphicImage – название файла в кавычках без расширения, graphicIndex – номер графики персонажа в файле; нумерация начинается с 0.
2) Синхронизация движения эвентов A и B (количество эвентов не ограничено), чтоб двигались по одинаковому маршруту:
Код:
let eventA = $gameMap.event(1);
let eventB = $gameMap.event(2);
let moveRouteA = eventA._moveRoute;
eventB.forceMoveRoute(eventA._moveRoute);
1, 2 - номера эвентов. В реальной игре это не тестировалось.
Что еще можно сделать: «Не вошедшее»
Бумеранг. Отражение «пулек» обратно в точку их старта. Телепорт-«крюк».
И все, на что вам хватит фантазии и силы в борьбе с мукером.
Последний раз редактировалось Darchan Kaen; 31.03.2022 в 09:06.
Причина: Дополнение о страницах эвентов-врагов
Социальные закладки